package com.hmall.service;

import com.hdmall.business.common.util.ResponseVo;
import com.hdmall.business.common.util.SDKConstants;
import com.hmall.mapper.MallOrderItemMapper;
import com.hmall.mapper.MallOrderMapper;
import com.hmall.mapper.MallProductMapper;
import com.hmall.model.MallOrderItem;
import com.hmall.model.MallProduct;
import com.hdmall.business.common.util.LogUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Service
public class RcvService {

    @Autowired
    private static MallOrderMapper orderMapper;

    @Autowired
    private static MallProductMapper productMapper;

    @Autowired
    private static MallOrderItemMapper orderItemMapper;

    public static void back(HttpServletRequest req, HttpServletResponse resp)throws Exception{
        LogUtil.writeLog("BackRcvResponse接收后台通知开始");
        String encoding = req.getParameter(SDKConstants.param_encoding);
        // 获取银联通知服务器发送的后台通知参数
        Map<String, String> reqParam = getAllRequestParam(req);
        LogUtil.printRequestLog(reqParam);
        ResponseVo res =new ResponseVo();
        res.setAccessType(reqParam.get("accessType"));
        res.setBizType(reqParam.get("bizType"));
        res.setCurrencyCode(reqParam.get("currencyCode"));
        res.setEncoding(reqParam.get("encoding"));
        res.setMerId(reqParam.get("merId"));
        res.setOrderId(reqParam.get("orderId"));
        res.setOrigRespCode(reqParam.get("origRespCode"));
        res.setOrigRespMsg(reqParam.get("origRespMsg"));
        res.setQueryId(reqParam.get("queryId"));
        res.setRespCode(reqParam.get("respCode"));
        res.setRespMsg(reqParam.get("respMsg"));
        res.setRespTime(reqParam.get("respTime"));
        res.setSettleAmt(reqParam.get("settleAmt"));
        res.setSettleCurrencyCode(reqParam.get("settleCurrencyCode"));
        res.setSettleDate(reqParam.get("settleDate"));
        res.setSignMethod(reqParam.get("signMethod"));
        res.setSignPubKeyCert(reqParam.get("signPubKeyCert"));
        res.setSignature(reqParam.get("signture"));
        res.setTraceNo(reqParam.get("traceNo"));
        res.setTraceTime(reqParam.get("traceTime"));
        res.setTxnAmt(reqParam.get("txnAmt"));
        res.setTxnSubType(reqParam.get("txnSubType"));
        res.setTxnTime(reqParam.get("txnTime"));
        res.setTxnType(reqParam.get("txnType"));
        res.setVersion(reqParam.get("version"));
        //重要！验证签名前不要修改reqParam中的键值对的内容，否则会验签不过
        if (!AcpService.validate(reqParam, encoding)) {
            LogUtil.writeLog("验证签名结果[失败].");
            //验签失败，需解决验签问题
            resp.sendError(500 );
        } else {
            LogUtil.writeLog("验证签名结果[成功].");
            //【注：为了安全验签成功才应该写商户的成功处理逻辑】交易成功，更新商户订单状态

            String orderId =reqParam.get("orderId"); //获取后台通知的数据，其他字段也可用类似方式获取
            String respCode = reqParam.get("respCode");
            //判断respCode=00、A6后，对涉及资金类的交易，请再发起查询接口查询，确定交易成功后·更新数据库。
            if(res.getRespCode().equals("00")||res.getRespCode().equals("A6")){
                if(res.getTxnType().equals("01")){
                    orderMapper.updateByOrderId("20",Integer.parseInt(res.getOrderId()));
                }else if(res.getTxnType().equals("04")){
                    orderMapper.updateByOrderId("60",Integer.parseInt(res.getOrderId()));
                    String orderNo=res.getOrderId();
                    List<MallOrderItem> orderItemList = orderItemMapper.getByOrderNo(Long.valueOf(orderNo));
                    for(MallOrderItem orderItem : orderItemList){
                        MallProduct product = productMapper.selectByPrimaryKey(orderItem.getProductId());
                        product.setStock(orderItem.getQuantity().intValue() + product.getStock());
                        productMapper.updateByPrimaryKeySelective(product);
                    }
                }
            }else{
                resp.sendError(500);
            }
        }
        LogUtil.writeLog("BackRcvResponse接收后台通知结束");
        //返回给银联服务器http 200  状态码
        resp.getWriter().write("ok");
    }

    public static String front(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        LogUtil.writeLog("FrontRcvResponse前台接收报文返回开始");
        String encoding = req.getParameter(SDKConstants.param_encoding);
        LogUtil.writeLog("返回报文中encoding=[" + encoding + "]");

        Map<String, String> respParam = getAllRequestParam(req);

        // 打印请求报文
        LogUtil.printRequestLog(respParam);
        Map<String, String> valideData = null;
        if (null != respParam && !respParam.isEmpty()) {
            Iterator<Map.Entry<String, String>> it = respParam.entrySet()
                    .iterator();
            valideData = new HashMap<String, String>(respParam.size());
            while (it.hasNext()) {
                Map.Entry<String, String> e = it.next();
                String key = (String) e.getKey();
                String value = (String) e.getValue();

                valideData.put(key, value);
            }
        }
        if (!AcpService.validate(valideData, encoding)) {

            LogUtil.writeLog("验证签名结果[失败].");
        } else {
            LogUtil.writeLog("验证签名结果[成功].");
            System.out.println(valideData.get("orderId")); //其他字段也可用类似方式获取
            String respCode = valideData.get("respCode");
            //判断respCode=00、A6后，对涉及资金类的交易，请再发起查询接口查询，确定交易成功后更新数据库。

        }


        LogUtil.writeLog("FrontRcvResponse前台接收报文返回结束");

        return respParam.get("respCode");
    }
    public static Map<String, String> getAllRequestParam(
            final HttpServletRequest request) {
        Map<String, String> res = new HashMap<String, String>();
        Enumeration<?> temp = request.getParameterNames();
        if (null != temp) {
            while (temp.hasMoreElements()) {
                String en = (String) temp.nextElement();
                String value = request.getParameter(en);
                res.put(en, value);
                // 在报文上送时，如果字段的值为空，则不上送<下面的处理为在获取所有参数数据时，判断若值为空，则删除这个字段>
                if (res.get(en) == null || "".equals(res.get(en))) {
                    // System.out.println("======为空的字段名===="+en);
                    res.remove(en);
                }
            }
        }
        return res;
    }

}
